x86: Allow TSC mode (emulate vs native) to be configured per domain.
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 28 Sep 2009 09:01:10 +0000 (10:01 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 28 Sep 2009 09:01:10 +0000 (10:01 +0100)
The default is to emulate. Old saved images will be restored with
legacy behaviour however (native TSC, no emulation).

Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
21 files changed:
tools/libxc/xc_domain.c
tools/libxc/xenctrl.h
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/XendConfig.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xm/create.py
tools/python/xen/xm/xenapi_create.py
xen/arch/x86/domain.c
xen/arch/x86/domctl.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/save.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/svm/vmcb.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/hvm/vpt.c
xen/arch/x86/time.c
xen/include/asm-x86/domain.h
xen/include/asm-x86/hvm/hvm.h
xen/include/asm-x86/time.h
xen/include/public/domctl.h

index 6ed4f52ec35fd12c37c3057cbeeb50381b2fe758..61cde9af39959deaf459487402c7c5c9ac7366bf 100644 (file)
@@ -466,6 +466,15 @@ int xc_domain_set_time_offset(int xc_handle,
     return do_domctl(xc_handle, &domctl);
 }
 
+int xc_domain_set_tsc_native(int xc_handle, uint32_t domid, int is_native)
+{
+    DECLARE_DOMCTL;
+    domctl.cmd = XEN_DOMCTL_set_tsc_native;
+    domctl.domain = (domid_t)domid;
+    domctl.u.set_tsc_native.is_native = is_native;
+    return do_domctl(xc_handle, &domctl);
+}
+
 int xc_domain_memory_increase_reservation(int xc_handle,
                                           uint32_t domid,
                                           unsigned long nr_extents,
index 1eade658a062f1f7c49eaf694939f59d9db92ec7..81ba26d61612c52d4b4d66be7e457beb765c02fb 100644 (file)
@@ -628,6 +628,8 @@ int xc_domain_set_time_offset(int xc_handle,
                               uint32_t domid,
                               int32_t time_offset_seconds);
 
+int xc_domain_set_tsc_native(int xc_handle, uint32_t domid, int is_native);
+
 int xc_domain_memory_increase_reservation(int xc_handle,
                                           uint32_t domid,
                                           unsigned long nr_extents,
index c7b484f9833bfb88d22877c0ff50c485bacb7946..3bff6a7f97a30eaafd8825a824b55e93aae9569e 100644 (file)
@@ -1459,6 +1459,20 @@ static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args)
     return zero;
 }
 
+static PyObject *pyxc_domain_set_tsc_native(XcObject *self, PyObject *args)
+{
+    uint32_t dom, is_native;
+
+    if (!PyArg_ParseTuple(args, "ii", &dom, &is_native))
+        return NULL;
+
+    if (xc_domain_set_tsc_native(self->xc_handle, dom, is_native) != 0)
+        return pyxc_error_to_exception();
+
+    Py_INCREF(zero);
+    return zero;
+}
+
 static PyObject *pyxc_domain_send_trigger(XcObject *self,
                                           PyObject *args,
                                           PyObject *kwds)
@@ -1981,6 +1995,14 @@ static PyMethodDef pyxc_methods[] = {
       " offset     [int]: Time offset from UTC in seconds.\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
+    { "domain_set_tsc_native",
+      (PyCFunction)pyxc_domain_set_tsc_native,
+      METH_VARARGS, "\n"
+      "Set a domain's TSC mode (emulate vs native)\n"
+      " dom        [int]: Domain whose TSC mode is being set.\n"
+      " is_native  [int]: 1=native, 0=emulate.\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
     { "domain_send_trigger",
       (PyCFunction)pyxc_domain_send_trigger,
       METH_VARARGS | METH_KEYWORDS, "\n"
index d5cd17cf1b9c3f4e8e857378ea50de7c4fae0121..9c84c26c6532467a132aeb45180c5734f83aa7a0 100644 (file)
@@ -162,6 +162,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
     'vncdisplay': int,
     'vnclisten': str,
     'timer_mode': int,
+    'tsc_native': int,
     'vpt_align': int,
     'viridian': int,
     'vncpasswd': str,
@@ -473,6 +474,9 @@ class XendConfig(dict):
             if not os.path.exists(self['platform']['device_model']):
                 raise VmError("device model '%s' not found" % str(self['platform']['device_model']))
 
+        if 'tsc_native' not in self['platform']:
+            self['platform']['tsc_native'] = 0
+
         if self.is_hvm():
             if 'timer_mode' not in self['platform']:
                 self['platform']['timer_mode'] = 1
index b7a4307ebbbdbc6b0f34f0655de703207496e819..b38a5fea4b73cdb5964054a2d1882fdf7b86200c 100644 (file)
@@ -2423,7 +2423,12 @@ class XendDomainInfo:
 
         self._recreateDom()
 
-        # Set timer configration of domain
+        # Set TSC mode of domain
+        tsc_native = self.info["platform"].get("tsc_native")
+        if arch.type == "x86" and tsc_native is not None:
+            xc.domain_set_tsc_native(self.domid, tsc_native)
+
+        # Set timer configuration of domain
         timer_mode = self.info["platform"].get("timer_mode")
         if hvm and timer_mode is not None:
             xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE,
index d7ed07b3c6320d369607c90dbf4495ec07ae647b..14f8aa64258492e931ed8217e6644ea9d9bae3d1 100644 (file)
@@ -221,6 +221,10 @@ gopts.var('timer_mode', val='TIMER_MODE',
           use="""Timer mode (0=delay virtual time when ticks are missed;
           1=virtual time is always wallclock time.""")
 
+gopts.var('tsc_native', val='TSC_NATIVE',
+          fn=set_int, default=0,
+          use="""TSC mode (0=emulate TSC, 1=native TSC).""")
+
 gopts.var('vpt_align', val='VPT_ALIGN',
           fn=set_int, default=1,
           use="Enable aligning all periodic vpt to reduce timer interrupts.")
@@ -715,6 +719,9 @@ def configure_image(vals):
     if vals.suppress_spurious_page_faults:
         config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults])
 
+    if vals.tsc_native is not None:
+        config_image.append(['tsc_native', vals.tsc_native])
+
     return config_image
     
 def configure_disks(config_devs, vals):
@@ -984,7 +991,7 @@ def make_config(vals):
                 config.append([n, v])
 
     map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
-                   'restart', 'on_poweroff',
+                   'restart', 'on_poweroff', 'tsc_native',
                    'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
                    'on_xend_start', 'on_xend_stop', 'target', 'cpuid',
                    'cpuid_check', 'machine_address_size', 'suppress_spurious_page_faults'])
index 27702635ae323d26bdfa0b4e2486fc3fbbfb15e8..903b29d21abccc2ed94578a67e2b3929f4ea1493 100644 (file)
@@ -1066,6 +1066,7 @@ class sxp2xml:
             'pci_msitranslate',
             'pci_power_mgmt',
             'xen_platform_pci',
+            'tsc_native'
         ]
 
         platform_configs = []
index 85e0ba0d59de4a5df0d31978c3f0c27aad8febcb..d9d6fb075e6b98ac1fa45a130eee40745966264a 100644 (file)
@@ -520,8 +520,6 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
         d->arch.cpuids[i].input[1] = XEN_CPUID_INPUT_UNUSED;
     }
 
-    /* For now, per-domain SoftTSC status is taken from global boot param. */
-    d->arch.vtsc = opt_softtsc;
     spin_lock_init(&d->arch.vtsc_lock);
 
     return 0;
index cb5bec7f712e8e9d502e6a19d39da22b0887c0bc..c5684c9a228907676bd940fe67b39fbada32420a 100644 (file)
@@ -1060,6 +1060,26 @@ long arch_do_domctl(
     }
     break;
 
+    case XEN_DOMCTL_set_tsc_native:
+    {
+        struct domain *d;
+
+        ret = -ESRCH;
+        d = rcu_lock_domain_by_id(domctl->domain);
+        if ( d == NULL )
+            break;
+
+        domain_pause(d);
+        d->arch.vtsc = !domctl->u.set_tsc_native.is_native;
+        if ( is_hvm_domain(d) )
+            hvm_set_rdtsc_exiting(d, d->arch.vtsc || hvm_gtsc_need_scale(d));
+        domain_unpause(d);
+
+        rcu_unlock_domain(d);
+        ret = 0;
+    }
+    break;
+
     case XEN_DOMCTL_suppress_spurious_page_faults:
     {
         struct domain *d;
index 7748b4579e35ce7e1313d6a9ee5f8a11c970df4d..b4e3708ca7b4a71514b336108956c95f79c0f3f8 100644 (file)
@@ -142,23 +142,23 @@ uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2)
     return TRAP_double_fault;
 }
 
-void hvm_enable_rdtsc_exiting(struct domain *d)
+void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable)
 {
     struct vcpu *v;
 
-    if ( opt_softtsc || !hvm_funcs.enable_rdtsc_exiting )
-        return;
-
     for_each_vcpu ( d, v )
-        hvm_funcs.enable_rdtsc_exiting(v);
+        hvm_funcs.set_rdtsc_exiting(v, enable);
 }
 
 int hvm_gtsc_need_scale(struct domain *d)
 {
     uint32_t gtsc_mhz, htsc_mhz;
 
+    if ( d->arch.vtsc )
+        return 0;
+
     gtsc_mhz = d->arch.hvm_domain.gtsc_khz / 1000;
-    htsc_mhz = opt_softtsc ? 1000 : ((uint32_t)cpu_khz / 1000);
+    htsc_mhz = (uint32_t)cpu_khz / 1000;
 
     d->arch.hvm_domain.tsc_scaled = (gtsc_mhz && (gtsc_mhz != htsc_mhz));
     return d->arch.hvm_domain.tsc_scaled;
@@ -171,38 +171,44 @@ static u64 hvm_h2g_scale_tsc(struct vcpu *v, u64 host_tsc)
     if ( !v->domain->arch.hvm_domain.tsc_scaled )
         return host_tsc;
 
-    htsc_khz = opt_softtsc ? 1000000 : cpu_khz;
+    htsc_khz = cpu_khz;
     gtsc_khz = v->domain->arch.hvm_domain.gtsc_khz;
     return muldiv64(host_tsc, gtsc_khz, htsc_khz);
 }
 
 void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc)
 {
-    uint64_t host_tsc, scaled_htsc;
+    uint64_t tsc;
 
-    if ( opt_softtsc )
-        host_tsc = hvm_get_guest_time(v);
+    if ( v->domain->arch.vtsc )
+    {
+        tsc = hvm_get_guest_time(v);
+    }
     else
-        rdtscll(host_tsc);
-
-    scaled_htsc = hvm_h2g_scale_tsc(v, host_tsc);
+    {
+        rdtscll(tsc);
+        tsc = hvm_h2g_scale_tsc(v, tsc);
+    }
 
-    v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - scaled_htsc;
+    v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - tsc;
     hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
 }
 
 u64 hvm_get_guest_tsc(struct vcpu *v)
 {
-    uint64_t host_tsc, scaled_htsc;
+    uint64_t tsc;
 
-    if ( opt_softtsc )
-        host_tsc = hvm_get_guest_time(v);
+    if ( v->domain->arch.vtsc )
+    {
+        tsc = hvm_get_guest_time(v);
+    }
     else
-        rdtscll(host_tsc);
-
-    scaled_htsc = hvm_h2g_scale_tsc(v, host_tsc);
+    {
+        rdtscll(tsc);
+        tsc = hvm_h2g_scale_tsc(v, tsc);
+    }
 
-    return scaled_htsc + v->arch.hvm_vcpu.cache_tsc_offset;
+    return tsc + v->arch.hvm_vcpu.cache_tsc_offset;
 }
 
 void hvm_migrate_timers(struct vcpu *v)
index af5aad72214c675e6ce7add8a2e2c35ca4e096b2..e409add6b6ef9dda925d9dadd96e68471c222750 100644 (file)
@@ -61,15 +61,14 @@ int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
                "does not match host (%#"PRIx32").\n", hdr->cpuid, eax);
 
     /* Restore guest's preferred TSC frequency. */
-    d->arch.hvm_domain.gtsc_khz = hdr->gtsc_khz;
-
-    if ( hdr->gtsc_khz && hvm_gtsc_need_scale(d) )
+    if ( hdr->gtsc_khz )
+        d->arch.hvm_domain.gtsc_khz = hdr->gtsc_khz;
+    if ( hvm_gtsc_need_scale(d) )
     {
-        hvm_enable_rdtsc_exiting(d);
+        hvm_set_rdtsc_exiting(d, 1);
         gdprintk(XENLOG_WARNING, "Domain %d expects freq %uMHz "
                 "but host's freq is %luMHz: trap and emulate rdtsc\n",
-                d->domain_id, hdr->gtsc_khz / 1000, opt_softtsc ? 1000ul :
-                cpu_khz / 1000);
+                d->domain_id, hdr->gtsc_khz / 1000, cpu_khz / 1000);
     }
 
     /* VGA state is not saved/restored, so we nobble the cache. */
index ead3eeca3108534c5dc4844faac143f83b5b8fd7..b34289878beee3c6c1617c0f2288c336ee058130 100644 (file)
@@ -619,6 +619,14 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
     v->arch.hvm_svm.vmcb->tsc_offset = offset;
 }
 
+static void svm_set_rdtsc_exiting(struct vcpu *v, bool_t enable)
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_RDTSC;
+    if ( enable )
+        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
+}
+
 static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
 {
     char *p;
@@ -845,7 +853,8 @@ static struct hvm_function_table svm_function_table = {
     .fpu_dirty_intercept  = svm_fpu_dirty_intercept,
     .msr_read_intercept   = svm_msr_read_intercept,
     .msr_write_intercept  = svm_msr_write_intercept,
-    .invlpg_intercept     = svm_invlpg_intercept
+    .invlpg_intercept     = svm_invlpg_intercept,
+    .set_rdtsc_exiting    = svm_set_rdtsc_exiting
 };
 
 static int svm_cpu_up(struct cpuinfo_x86 *c)
index 6f1f087d88171cc6945d9d8525ee7c3173cac84f..202cc9810d79533ed9dfe58e855523979f47d37e 100644 (file)
@@ -167,7 +167,7 @@ static int construct_vmcb(struct vcpu *v)
 
     /* TSC. */
     vmcb->tsc_offset = 0;
-    if ( opt_softtsc )
+    if ( v->domain->arch.vtsc )
         vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
 
     /* Guest EFER. */
index 11dc4685212149f36c0a40a9bfcc48b8ed487d5a..724d0a61d3ac35183f06c392a723ec76948295e3 100644 (file)
@@ -133,13 +133,14 @@ static void vmx_init_vmcs_config(void)
            CPU_BASED_MOV_DR_EXITING |
            CPU_BASED_ACTIVATE_IO_BITMAP |
            CPU_BASED_USE_TSC_OFFSETING |
-           (opt_softtsc ? CPU_BASED_RDTSC_EXITING : 0));
+           CPU_BASED_RDTSC_EXITING);
     opt = (CPU_BASED_ACTIVATE_MSR_BITMAP |
            CPU_BASED_TPR_SHADOW |
            CPU_BASED_MONITOR_TRAP_FLAG |
            CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
     _vmx_cpu_based_exec_control = adjust_vmx_controls(
         min, opt, MSR_IA32_VMX_PROCBASED_CTLS);
+    _vmx_cpu_based_exec_control &= ~CPU_BASED_RDTSC_EXITING;
 #ifdef __x86_64__
     if ( !(_vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW) )
     {
@@ -553,6 +554,9 @@ static int construct_vmcs(struct vcpu *v)
     __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
 
     v->arch.hvm_vmx.exec_control = vmx_cpu_based_exec_control;
+    if ( d->arch.vtsc )
+        v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
+
     v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control;
 
     if ( paging_mode_hap(d) )
index c51f560ab330296f34c7e64bd09123a72e451242..151d3a5be0328ff297357ffbfa682843a4c6d12f 100644 (file)
@@ -949,13 +949,15 @@ static void vmx_set_tsc_offset(struct vcpu *v, u64 offset)
     vmx_vmcs_exit(v);
 }
 
-static void vmx_enable_rdtsc_exiting(struct vcpu *v)
+static void vmx_set_rdtsc_exiting(struct vcpu *v, bool_t enable)
 {
     vmx_vmcs_enter(v);
-    v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
+    v->arch.hvm_vmx.exec_control &= ~CPU_BASED_RDTSC_EXITING;
+    if ( enable )
+        v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING;
     __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control);
     vmx_vmcs_exit(v);
- }
+}
 
 static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page)
 {
@@ -1414,7 +1416,7 @@ static struct hvm_function_table vmx_function_table = {
     .invlpg_intercept     = vmx_invlpg_intercept,
     .set_uc_mode          = vmx_set_uc_mode,
     .set_info_guest       = vmx_set_info_guest,
-    .enable_rdtsc_exiting = vmx_enable_rdtsc_exiting
+    .set_rdtsc_exiting    = vmx_set_rdtsc_exiting
 };
 
 static unsigned long *vpid_bitmap;
index 9a0bb06429d0995dbe2de2d53a829c0d92165923..22d66f6fed4a0f7b9af9dc541be0f1c965390953 100644 (file)
@@ -33,7 +33,7 @@ void hvm_init_guest_time(struct domain *d)
     pl->stime_offset = -(u64)get_s_time();
     pl->last_guest_time = 0;
 
-    d->arch.hvm_domain.gtsc_khz = opt_softtsc ? 1000000 : cpu_khz;
+    d->arch.hvm_domain.gtsc_khz = cpu_khz;
     d->arch.hvm_domain.tsc_scaled = 0;
 }
 
index a4bb329524a4083ae3e181293dbd65d008fd0699..f21861d7e68b84ad42c015f1f1bb6f4946749863 100644 (file)
@@ -36,9 +36,6 @@
 static char __initdata opt_clocksource[10];
 string_param("clocksource", opt_clocksource);
 
-int opt_softtsc;
-boolean_param("softtsc", opt_softtsc);
-
 /*
  * opt_consistent_tscs: All TSCs tick at the exact same rate, allowing
  * simplified system time handling.
@@ -1436,20 +1433,18 @@ struct tm wallclock_time(void)
  * PV SoftTSC Emulation.
  */
 
-static unsigned long rdtsc_kerncount, rdtsc_usercount;
-
 void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs)
 {
     s_time_t now;
 
     if ( guest_kernel_mode(v, regs) )
     {
-        rdtsc_kerncount++;
+        v->domain->arch.vtsc_kerncount++;
         rdtsc(regs->eax, regs->edx);
     }
     else
     { 
-        rdtsc_usercount++;
+        v->domain->arch.vtsc_kerncount++;
         spin_lock(&v->domain->arch.vtsc_lock);
         now = get_s_time() + v->domain->arch.vtsc_stime_offset;
         if ( (int64_t)(now - v->domain->arch.vtsc_last) > 0 )
@@ -1462,10 +1457,28 @@ void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs)
     }
 }
 
+/* vtsc may incur measurable performance degradation, diagnose with this */
 static void dump_softtsc(unsigned char key)
 {
-    printk("softtsc count: %lu kernel, %lu user\n",
-           rdtsc_kerncount, rdtsc_usercount);
+    struct domain *d;
+    int domcnt = 0;
+
+    for_each_domain ( d )
+    {
+        if ( !d->arch.vtsc )
+            continue;
+        if ( is_hvm_domain(d) )
+            printk("dom%u (hvm) vtsc count: %"PRIu64" total\n",
+                   d->domain_id, d->arch.vtsc_kerncount);
+        else
+            printk("dom%u vtsc count: %"PRIu64" kernel, %"PRIu64" user\n",
+                   d->domain_id, d->arch.vtsc_kerncount,
+                   d->arch.vtsc_usercount);
+        domcnt++;
+    }
+
+    if ( !domcnt )
+            printk("All domains have native TSC\n");
 }
 
 static struct keyhandler dump_softtsc_keyhandler = {
@@ -1476,8 +1489,7 @@ static struct keyhandler dump_softtsc_keyhandler = {
 
 static int __init setup_dump_softtsc(void)
 {
-    if ( opt_softtsc )
-        register_keyhandler('s', &dump_softtsc_keyhandler);
+    register_keyhandler('s', &dump_softtsc_keyhandler);
     return 0;
 }
 __initcall(setup_dump_softtsc);
index cf65772ebb280089e51e505d0fc5a8cd7188721b..6edbe3b21524bc14f02b1c71f5b7320e4756a8cf 100644 (file)
@@ -304,6 +304,8 @@ struct arch_domain
     bool_t vtsc;
     s_time_t vtsc_last;
     spinlock_t vtsc_lock;
+    uint64_t vtsc_kerncount; /* for hvm, counts all vtsc */
+    uint64_t vtsc_usercount; /* not used for hvm */
     int64_t vtsc_stime_offset;
 } __cacheline_aligned;
 
index 76e06d7db62dc434050c0b068a0b4444857fdc48..327a1c9737150878bc445bfdd93eb15451cdb0cd 100644 (file)
@@ -131,7 +131,7 @@ struct hvm_function_table {
     void (*invlpg_intercept)(unsigned long vaddr);
     void (*set_uc_mode)(struct vcpu *v);
     void (*set_info_guest)(struct vcpu *v);
-    void (*enable_rdtsc_exiting)(struct vcpu *v);
+    void (*set_rdtsc_exiting)(struct vcpu *v, bool_t);
 };
 
 extern struct hvm_function_table hvm_funcs;
@@ -288,7 +288,7 @@ int hvm_event_needs_reinjection(uint8_t type, uint8_t vector);
 
 uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2);
 
-void hvm_enable_rdtsc_exiting(struct domain *d);
+void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable);
 int hvm_gtsc_need_scale(struct domain *d);
 
 static inline int hvm_cpu_up(void)
index ec06313f952be64be6b07bb755357b58419fdc88..dac53bcc2599a0f983db44501d96dee5aa30ef81 100644 (file)
@@ -41,7 +41,6 @@ int pit_broadcast_is_available(void);
 uint64_t acpi_pm_tick_to_ns(uint64_t ticks);
 uint64_t ns_to_acpi_pm_tick(uint64_t ns);
 
-extern int opt_softtsc;
 void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs);
 
 #endif /* __X86_TIME_H__ */
index f7b1fc5ec72b639bae64c788fdcab139b5a70c7b..3b4cb51796324bd73edb3cb00a67c2e67d718c39 100644 (file)
@@ -401,7 +401,11 @@ struct xen_domctl_settimeoffset {
 typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
 
+#define XEN_DOMCTL_set_tsc_native    57
+typedef struct xen_domctl_set_tsc_native {
+    uint32_t is_native; /* IN: 0: TSC is emulated; 1: TSC is host TSC */
+} xen_domctl_set_tsc_native_t;
+
 #define XEN_DOMCTL_gethvmcontext     33
 #define XEN_DOMCTL_sethvmcontext     34
 typedef struct xen_domctl_hvmcontext {
@@ -672,6 +676,7 @@ struct xen_domctl {
         struct xen_domctl_hypercall_init    hypercall_init;
         struct xen_domctl_arch_setup        arch_setup;
         struct xen_domctl_settimeoffset     settimeoffset;
+        struct xen_domctl_set_tsc_native    set_tsc_native;
         struct xen_domctl_real_mode_area    real_mode_area;
         struct xen_domctl_hvmcontext        hvmcontext;
         struct xen_domctl_hvmcontext_partial hvmcontext_partial;